package handle

import (
	"context"
	"errors"
	"gitee.com/crack007/goose"
	"gitee.com/crack007/goose/core"
	"gitee.com/crack007/goose/core/ws"
	"gitee.com/crack007/goose/injection"
	"github.com/crack007/go-im/pb"
	"github.com/crack007/go-im/src/common/config"
	"github.com/crack007/go-im/src/common/model"
	commonService "github.com/crack007/go-im/src/common/service"
	"github.com/crack007/go-im/src/module/ws/job"
	"github.com/crack007/go-im/src/module/ws/register"
	"github.com/crack007/go-im/src/module/ws/service"
	"google.golang.org/grpc"
)

type ImServerHandle struct {
	sessionBuilder *ws.SessionBuilder
	ws.DefaultServerHandle
	IsSlave    bool
	MasterIp   string
	MasterPort uint16
	OuterIp    string
}

func NewImServerHandle(sessionBuilder *ws.SessionBuilder) *ImServerHandle {
	return &ImServerHandle{sessionBuilder: sessionBuilder}
}
func (h *ImServerHandle) OnInitConfig() {
	config.InitAppConfig()
	// 读取应用配置字段
	h.sessionBuilder.SetIdleTimeout(config.WsConfig.IdleTimeout)
	h.GetServer().SetPort(config.GetNodeConfig().NodePort)
}

func (h *ImServerHandle) OnInitInject() []injection.Service {
	return []injection.Service{injection.MYSQL_SERVICE, injection.REDIS_SERVICE, injection.GRPC_SERVER_SERVICE}
}
func (h *ImServerHandle) OnInitRouter() {
	userSessionHandle := &UserSessionHandle{}
	ws.RegisterRoute(h.GetServer(), "/user", userSessionHandle)
}

func (h *ImServerHandle) OnInitService() {
	register.ServiceRegister()
}

func (h *ImServerHandle) OnStart() error {
	wsServer := h.GetServer()
	service.UserManagerService.SessionManager = wsServer.SessionManager
	service.UserManagerService.MessageManager = wsServer.MessageManager
	if h.IsSlave {
		if h.MasterIp == "" || h.MasterPort == 0 {
			return errors.New("slave模式下，必须指定master节点的ip和端口")
		}
	}
	currentNode := model.NewNodeModel()
	currentNode.Id = config.GetNodeConfig().NodeName
	currentNode.Ip = config.GetNodeConfig().NodeAddr
	currentNode.Port = service.GetGrpcServer().Port
	currentNode.WsPort = config.GetNodeConfig().NodePort
	currentNode.IsMaster = !h.IsSlave
	service.NodeGrpcService.CurrentNode = currentNode
	goose.GetLogger().Debug("ip=%s", currentNode.Ip)
	service.NodeGrpcService.AddNode(currentNode)
	if !h.IsSlave {
		commonService.NodeService.Store(currentNode)
	}
	// go monitor.NewPrometheus()
	job.SubmitStatJob(10*1000, wsServer)

	wsServer.AddGracefulTask(core.NewGracefulTask(func(ctx context.Context) {
		rpcServer := service.GetGrpcServer()
		rpcServer.SetRegisterServer(func(grpcServer *grpc.Server) {
			pb.RegisterNodeServiceServer(grpcServer, service.NodeGrpcService)
		})
		rpcServer.Bootstrap(ctx)
	}))
	if h.IsSlave {
		slaveRegisterModel := model.NewSlaveRegisterModel()
		slaveRegisterModel.Slave.OutIP = config.GetNodeConfig().NodeAddr
		slaveRegisterModel.Slave.Port = config.GrpcConfig.Port
		slaveRegisterModel.Slave.WsPort = config.GetNodeConfig().NodePort
		slaveRegisterModel.Slave.Id = config.GetNodeConfig().NodeName
		slaveRegisterModel.Master.Port = h.MasterPort
		slaveRegisterModel.Master.OutIP = h.MasterIp
		err := service.SlaveService.Register(slaveRegisterModel)
		if err != nil {
			goose.GetLogger().Error("SlaveService.Register err: %s", err.Error())
			panic(err)
		}
	}
	return nil
}

func (h *ImServerHandle) OnShutdown() {
	service.ServerService.Shutdown(h.GetServer())
}
